﻿using System;
using System.Collections.Generic;

using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Xps.Packaging;
using System.Xml;

namespace SharpSoft.WPF.Controls
{
    /// <summary>
    /// 用于展示多种媒体类型
    /// </summary>
    [TemplatePart(Name = "content", Type = typeof(ContentPresenter))]
    public class MultiMediaControl : Control, IUriContext
    {
        static MultiMediaControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiMediaControl), new FrameworkPropertyMetadata(typeof(MultiMediaControl)));
        }
        ContentPresenter cp;

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            cp = (ContentPresenter)this.GetTemplateChild("content");
            this.updateSource();
        }

        #region 属性

        /// <summary>
        /// 媒体源
        /// </summary>
        public Uri Source
        {
            get { return (Uri)GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }

        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register("Source", typeof(Uri), typeof(MultiMediaControl), new PropertyMetadata(null));


        public Uri BaseUri { get; set; }

        /// <summary>
        /// 媒体的拉伸行为
        /// </summary>
        public Stretch Stretch
        {
            get { return (Stretch)GetValue(StretchProperty); }
            set { SetValue(StretchProperty, value); }
        }


        public static readonly DependencyProperty StretchProperty =
            DependencyProperty.Register("Stretch", typeof(Stretch), typeof(MultiMediaControl), new PropertyMetadata(Stretch.Uniform));


        /// <summary>
        /// 是否自动开始播放媒体
        /// </summary>
        public bool AutoPlay
        {
            get { return (bool)GetValue(AutoPlayProperty); }
            set { SetValue(AutoPlayProperty, value); }
        }

        public static readonly DependencyProperty AutoPlayProperty =
            DependencyProperty.Register("AutoPlay", typeof(bool), typeof(MultiMediaControl), new PropertyMetadata(false));


        /// <summary>
        /// 是否自动重放媒体
        /// </summary>
        public bool AutoReplay
        {
            get { return (bool)GetValue(AutoReplayProperty); }
            set { SetValue(AutoReplayProperty, value); }
        }

        public static readonly DependencyProperty AutoReplayProperty =
            DependencyProperty.Register("AutoReplay", typeof(bool), typeof(MultiMediaControl), new PropertyMetadata(false));


        /// <summary>
        /// 左右声道音量平衡
        /// </summary>
        public double Balance
        {
            get { return (double)GetValue(BalanceProperty); }
            set { SetValue(BalanceProperty, value); }
        }

        public static readonly DependencyProperty BalanceProperty =
            DependencyProperty.Register("Balance", typeof(double), typeof(MultiMediaControl), new PropertyMetadata(0d));


        /// <summary>
        /// 视频音量
        /// </summary>
        public double Volume
        {
            get { return (double)GetValue(VolumeProperty); }
            set { SetValue(VolumeProperty, value); }
        }

        public static readonly DependencyProperty VolumeProperty =
            DependencyProperty.Register("Volume", typeof(double), typeof(MultiMediaControl), new PropertyMetadata(1d));


        /// <summary>
        /// 是否静音
        /// </summary>
        public bool IsMuted
        {
            get { return (bool)GetValue(IsMutedProperty); }
            set { SetValue(IsMutedProperty, value); }
        }

        public static readonly DependencyProperty IsMutedProperty =
            DependencyProperty.Register("IsMuted", typeof(bool), typeof(MultiMediaControl), new PropertyMetadata(false));



        /// <summary>
        /// 获取当前用于展示媒体的控件实例
        /// </summary>
        public FrameworkElement MediaControl
        {
            get
            {
                return cp.Content as FrameworkElement;
            }
        }
        /// <summary>
        /// 识别为长图的高宽比例，为null表示不支持长图。
        /// </summary>
        public double? LongImageRatio
        {
            get { return (double?)GetValue(LongImageRatioProperty); }
            set { SetValue(LongImageRatioProperty, value); }
        }

        public static readonly DependencyProperty LongImageRatioProperty =
            DependencyProperty.Register("LongImageRatio", typeof(double?), typeof(MultiMediaControl), new PropertyMetadata(null));

        /// <summary>
        /// 图片加载模式
        /// </summary> 
        public ImageLoadMode ImageLoadMode
        {
            get { return (ImageLoadMode)GetValue(ImageLoadModeProperty); }
            set { SetValue(ImageLoadModeProperty, value); }
        }

        public static readonly DependencyProperty ImageLoadModeProperty =
            DependencyProperty.Register("ImageLoadMode", typeof(ImageLoadMode), typeof(MultiMediaControl), new PropertyMetadata(ImageLoadMode.Default));



        #endregion

        #region 方法
        /// <summary>
        /// 显示XAML文件
        /// </summary>
        private void ShowXAML()
        {
            if (this.Source != null)
            {
                var xmlReader = XmlTextReader.Create(this.Source.ToString(), null);
                object obj = XamlReader.Load(xmlReader);
                if (obj is UIElement ui)
                {
                    this.cp.Content = ui;
                }
            }

        }




        /// <summary>
        /// 显示图片
        /// </summary>
        private void ShowImage()
        {
            BitmapImage bmp;

            if (this.ImageLoadMode == ImageLoadMode.Default)
            {
                bmp = new BitmapImage(this.Source);
            }
            else if (this.ImageLoadMode == ImageLoadMode.AsStream)
            {
                if (this.Source.IsFile)
                {
                    bmp = BitmapHelper.Load(this.Source.LocalPath);
                }
                else
                {
                    bmp = new BitmapImage(this.Source);
                }
            }
            else if (this.ImageLoadMode == ImageLoadMode.Async)
            {
                bmp = new BitmapImage(this.Source);
            }
            else
            {
                throw new Exception("未知的图片加载模式");
            }

            //if (this.Source.IsFile)
            //{//如果是本地文件则同步加载
            //    bmp = new BitmapImage();
            //    using (var stream = new System.IO.FileStream(this.Source.LocalPath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            //    {
            //        bmp.BeginInit();
            //        bmp.CacheOption = BitmapCacheOption.OnLoad;
            //        bmp.StreamSource = stream;
            //        bmp.EndInit();
            //        bmp.Freeze();
            //    }
            //}
            //else
            //{
            //    bmp = new BitmapImage(this.Source);
            //}

            var ratio = this.LongImageRatio;
            if (ratio.HasValue && bmp.PixelHeight / (double)bmp.PixelWidth > ratio.Value)
            {//长图
                ScrollViewer sv = new ScrollViewer() { PanningMode = PanningMode.VerticalOnly, HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled };
                sv.ManipulationBoundaryFeedback += Sv_ManipulationBoundaryFeedback;
                Image longImg = new Image()
                {
                    Source = bmp,
                    HorizontalAlignment = HorizontalAlignment.Stretch,
                    Stretch = Stretch.UniformToFill,
                    StretchDirection = StretchDirection.DownOnly
                };
                sv.Content = longImg;
                this.cp.Content = sv;
                return;
            }
            Image image = new Image()
            {
                Source = bmp,
                HorizontalAlignment = HorizontalAlignment.Stretch,
                VerticalAlignment = VerticalAlignment.Stretch,
                Stretch = this.Stretch
            };
            this.cp.Content = image;

        }

        private static void Sv_ManipulationBoundaryFeedback(object sender, System.Windows.Input.ManipulationBoundaryFeedbackEventArgs e)
        {
            e.Handled = true;
        }
        /// <summary>
        /// 显示序列帧
        /// </summary>
        private void ShowSIP()
        {
            SequenceImage si = new SequenceImage()
            {
                Source = this.Source.OriginalString,
                AutoPlay = this.AutoPlay,
            };
            //SIP的循环播放不受此控件设置的影响，使用sip文件内置的循环次数信息来控制
            //if (this.AutoReplay)
            //{
            //    si.LoopTimes = null;
            //}
            //else
            //{
            //    si.LoopTimes = 1;
            //}
            this.cp.Content = si;
        }
        /// <summary>
        /// 显示视频
        /// </summary>
        private void ShowVideo()
        {
            VideoPlayer media = new VideoPlayer()
            {
                Source = this.Source,
                AutoPlay = this.AutoPlay,
                AutoReplay = this.AutoReplay,
                Stretch = this.Stretch,
                Balance = this.Balance,
                Volume = this.Volume,
            };
            Binding bindingBalance = new Binding() { Source = this, Path = new PropertyPath(MultiMediaControl.BalanceProperty) };
            media.SetBinding(VideoPlayer.BalanceProperty, bindingBalance);
            Binding bindingVolume = new Binding() { Source = this, Path = new PropertyPath(MultiMediaControl.VolumeProperty) };
            media.SetBinding(VideoPlayer.VolumeProperty, bindingVolume);
            Binding bindingIsMuted = new Binding() { Source = this, Path = new PropertyPath(MultiMediaControl.IsMutedProperty) };
            media.SetBinding(VideoPlayer.IsMutedProperty, bindingIsMuted);
            this.cp.Content = media;
        }
        /// <summary>
        /// 显示自定义媒体
        /// </summary>
        private void ShowCustomMedia()
        {
            CustomMedia media = new CustomMedia()
            {
                Source = this.Source,
            };
            this.cp.Content = media;
        }

        #region 显示XPS文档

        private static Style docViewerStyle;//静态储存文档阅读器的样式
        /// <summary>
        /// 显示XPS文档
        /// </summary>
        private void ShowXPSDocument()
        {
            DocumentViewer dv = new DocumentViewer() { MaxPagesAcross = 1 };
            dv.MouseWheel += Dv_MouseWheel;
            dv.Loaded += Dv_Loaded;
            dv.PageViewsChanged += Dv_PageViewsChanged;
            dv.SizeChanged += Dv_SizeChanged;
            DocumentViewerExtension.SetPagingButtonVisible(dv, true);

            XpsDocument doc = new XpsDocument(this.Source.LocalPath, System.IO.FileAccess.Read);
            dv.Document = doc.GetFixedDocumentSequence();
            if (docViewerStyle == null)
            {
                ResourceDictionary rd = new ResourceDictionary();
                rd.Source = ResourceHelper.GetLocationUri("Controls/MultiMedia/CustomDocumentViewerStyle.xaml");
                docViewerStyle = rd[typeof(DocumentViewer)] as Style;
            }
            dv.Style = docViewerStyle;
            this.cp.Content = dv;
            dv.FirstPage();
            dv.FitToMaxPagesAcross(1);
        }

        private void Dv_MouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
        {
            // e.Handled = true;
        }

        private void Dv_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            var dv = sender as DocumentViewer;
            dv.FitToMaxPagesAcross(1);

        }

        private void Dv_Loaded(object sender, RoutedEventArgs e)
        {
            var dv = sender as DocumentViewer;
            dv.FitToMaxPagesAcross(1);

        }

        private void Dv_PageViewsChanged(object sender, EventArgs e)
        {
            var dv = sender as DocumentViewer;
            dv.FitToMaxPagesAcross(1);
        }
        #endregion


        /// <summary>
        /// 清除当前媒体内容， 一般在切换内容前调用
        /// </summary>
        protected virtual void OnDestoryCurrentContent()
        {
            if (cp.Content is VideoPlayer media)
            {
                media.Stop();
                media.Source = null;
            }
            cp.Content = null;

        }

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property == SourceProperty)
            {
                this.updateSource();
            }
            else if (e.Property == StretchProperty)
            {
                if (this.cp != null)
                {
                    if (cp.Content is VideoPlayer media)
                    {
                        media.Stretch = this.Stretch;
                    }
                    else if (cp.Content is Image img)
                    {
                        img.Stretch = this.Stretch;
                    }
                    else if (cp.Content is SequenceImage si)
                    {
                        si.Stretch = this.Stretch;
                    }
                }

            }
        }

        private void updateSource()
        {
            if (this.cp == null)
            {
                return;
            }
            if (Source == null)
            {
                this.cp.Content = null;
                return;
            }
            var mt = GetMediaType(Source);
            this.OnDestoryCurrentContent();
            switch (mt)
            {
                case MediaType.Image:
                    this.ShowImage();
                    break;
                case MediaType.Video:
                    this.ShowVideo();
                    break;
                case MediaType.CustomMedia:
                    this.ShowCustomMedia();
                    break;
                case MediaType.SequenceImage:
                    this.ShowSIP();
                    break;
                case MediaType.XPSDocument:
                    this.ShowXPSDocument();
                    break;
                case MediaType.XAML:
                    this.ShowXAML();
                    break;
                case MediaType.Text:
                case MediaType.Audio:
                case MediaType.Unknow:
                default:
                    cp.Content = "不支持的媒体类型。[unsupported media type.]";
                    break;
            }
        }
        /// <summary>
        /// 获取媒体类型
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static MediaType GetMediaType(string uri)
        {
            if (string.IsNullOrEmpty(uri))
            {
                return MediaType.Unknow;
            }
            var ext = System.IO.Path.GetExtension(uri);
            if (ext == null)
            {
                return MediaType.Unknow;
            }
            switch (ext.ToLower())
            {
                case ".sip":
                    return MediaType.SequenceImage;
                case ".csm":
                    return MediaType.CustomMedia;
                case ".xaml":
                    return MediaType.XAML;
                case ".jpg":
                case ".png":
                case ".jpeg":
                case ".bmp":
                    return MediaType.Image;
                case ".mp4":
                case ".wmv":
                case ".avi":
                case ".mpg":
                case ".mkv":
                case ".flv":
                    return MediaType.Video;
                case ".mp3":
                case ".wma":
                case ".wav":
                case ".midi":
                    return MediaType.Audio;
                case ".txt":
                case ".xml":
                case ".html":
                case ".css":
                case ".js":
                case ".csv":
                    return MediaType.Text;
                case ".xps":
                case ".oxps":
                    return MediaType.XPSDocument;
                case ".pdf":
                case ".xls":
                case ".xlsx":
                case ".doc":
                case ".docx":
                case ".ppt":
                case ".pptx":

                default:
                    return MediaType.Unknow;
            }
        }
        /// <summary>
        /// 获取媒体类型
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static MediaType GetMediaType(Uri uri)
        {
            if (uri == null)
            {
                return MediaType.Unknow;
            }
            return GetMediaType(uri.LocalPath);
        }

        /// <summary>
        /// 获取目录中所有支持的媒体类型的文件
        /// </summary>
        /// <param name="folder"></param>
        /// <returns></returns>
        public static string[] GetSupportedFilesInFolder(string folder)
        {
            List<string> list = new List<string>();
            if (System.IO.Directory.Exists(folder))
            {
                var files = System.IO.Directory.GetFiles(folder);
                foreach (var item in files)
                {
                    var mediaType = MultiMediaControl.GetMediaType(item);
                    if (mediaType != MultiMediaControl.MediaType.Unknow)
                    {
                        list.Add(item);
                    }
                }
            }
            return list.ToArray();
        }
        #endregion

        /// <summary>
        /// 媒体类型
        /// </summary>
        public enum MediaType
        {
            /// <summary>
            /// 未知类型
            /// </summary>
            Unknow,
            /// <summary>
            /// 动态XAML文件
            /// </summary>
            XAML,
            /// <summary>
            /// XPS文档流
            /// </summary>
            XPSDocument,
            /// <summary>
            /// 纯文本
            /// </summary>
            Text,
            /// <summary>
            /// 图片
            /// </summary>
            Image,
            /// <summary>
            /// 视频
            /// </summary>
            Video,
            /// <summary>
            /// 音频
            /// </summary>
            Audio,
            /// <summary>
            /// 自定义的序列帧文件
            /// </summary>
            SequenceImage,
            /// <summary>
            /// 自定义媒体内容
            /// </summary>
            CustomMedia
        }
    }
}
